/**********************************************************
*
*   @file    useri2c.c
*   @author  Derrick Wang
*   @time    2018-4-26
*		@brief   i2c协议解析文件
*
*
***********************************************************/

#include "main.h"
#include "stm32f0xx_hal.h"
#include "userI2c.h"
#include "i2c.h"
#include "userI2cReg.h" 

extern struct userI2cRegStruct userI2cRegList[];

uint8_t userI2cCmdState;       //用来记录和ikbit的i2c通讯协议的状态
uint8_t userI2cRecBuffer[I2C_REC_BUF_SIZE]; //存放从主机接收到的数据
uint8_t userI2cTransBuffer[I2C_TRANS_BUF_SIZE];
uint8_t userI2cNowRegNum;      //记录当前接收到的寄存器序号
uint8_t userCmdOverTimeCheck;  //超时检测计数
uint8_t userI2cOpDataAdd;      //从option byte userdata0里面读取出来的地址，如果读出来的值在1-127之间，就把它配置为模块的地址



static void user_I2cRecDeal(uint8_t *buf,uint8_t size);
static void user_I2cCmdError(void);
static void user_I2cCmdStart(void);
static void user_I2cReadOptionAdd(void);


#define I2C_CMD_START          0X00
#define I2C_CMD_WAIT_REC       0X01   
#define I2C_CMD_RECEIVE        0X02
#define I2C_CMD_REC_END        0X03
#define I2C_CMD_EXECUTE        0X04
#define I2C_CMD_WAIT_TRANSMIT  0X05
#define I2C_CMD_TRANSMIT       0X06
#define I2C_CMD_ERROR          0X07


//清除i2c发送寄存器数据
static void user_I2cFlushTxdr(I2C_HandleTypeDef *hi2c)
{
  /* If a pending TXIS flag is set */
  /* Write a dummy data in TXDR to clear it */
  if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET)
  {
    hi2c->Instance->TXDR = 0x00U;
  }

  /* Flush TX register if not empty */
  if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET)
  {
    __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_TXE);
  }
}
//软复位i2c
void user_I2cSoftReset(I2C_HandleTypeDef *hi2c)
{
	hi2c->Instance->CR2 |= I2C_CR2_NACK;   //关闭应答信号
	I2C_RESET_CR2(hi2c);
	//根据手册上描述设置i2c软复位，要对PE进行写读写三步操作
	__HAL_I2C_DISABLE(hi2c);
	if((hi2c->Instance->CR1|I2C_CR1_PE)==0)  //读取PE位是否为0
	{
	}
	__HAL_I2C_ENABLE(hi2c);
}

//i2c从机发送方向处理函数
void user_I2C_EV_SlaveTransmit()
{
		if(userI2cCmdState==I2C_CMD_WAIT_TRANSMIT)
		{
			__HAL_I2C_ENABLE_IT(&hi2c1, I2C_IT_STOPI|I2C_IT_TXI|I2C_IT_NACKI|I2C_IT_ERRI); //打开STOP信号中断和发送为空中断和无应答信号中断
			userI2cCmdState=I2C_CMD_TRANSMIT;
			  
		}
		else    //错误的匹配到了主机读取地址
		{
				user_I2cFlushTxdr(&hi2c1); //清除i2c发送寄存器
				userI2cCmdState=I2C_CMD_ERROR;
			  user_I2cCmdError();
		}
}
//i2c从机接收方向处理函数
void user_I2C_EV_SlaveReceive()
{
		if(userI2cCmdState==I2C_CMD_WAIT_REC) //只有这两种情况匹配到地址以后才会进行接收
		{
				__HAL_I2C_ENABLE_IT(&hi2c1, I2C_IT_STOPI|I2C_IT_RXI|I2C_IT_ERRI); //打开STOP信号中断和RXNE中断
				userI2cCmdState=I2C_CMD_RECEIVE;
		}
		else
		{
			userI2cCmdState=I2C_CMD_ERROR;
			user_I2cCmdError();
		}
}

//I2C正常事件中断服务函数
void user_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c)
{
  uint32_t itflags   = READ_REG(hi2c->Instance->ISR);
  uint32_t itsources = READ_REG(hi2c->Instance->CR1);
  if(((itflags & I2C_FLAG_ADDR) != RESET) && ((itsources & I2C_IT_ADDRI) != RESET))     //地址匹配中断
	{
		__HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);  //清除地址匹配中断标志位
		if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_DIR))  //方向为从发送
		{
				user_I2C_EV_SlaveTransmit();
		}
		else  //方向为从接收
		{
				user_I2C_EV_SlaveReceive();
		}
	}
	else if (((itflags & I2C_FLAG_AF) != RESET) && ((itsources & I2C_IT_NACKI) != RESET)) //NACK信号中断
	{
		__HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); //清除中断标志位
		user_I2cFlushTxdr(hi2c);                 //清除发送寄存器里面的内容
		if(hi2c->XferCount!=hi2c->XferSize)      //从机收到主机NACK信号时，发送的数据量和设定的不相等
		{
			
		}
	}
	else if(((itflags & I2C_FLAG_RXNE) != RESET) && ((itsources & I2C_IT_RXI) != RESET))  //RXNE中断
	{
			/* Read data from RXDR */
			if(hi2c->XferCount<I2C_REC_BUF_SIZE-1)  //留一个byte最为超出接收范围暂存区
			{
				(*hi2c->pBuffPtr++) = hi2c->Instance->RXDR;
			   hi2c->XferCount++;
			}
			else (*hi2c->pBuffPtr)=hi2c->Instance->RXDR;
	}
	else if (((itflags & I2C_FLAG_TXIS) != RESET) && ((itsources & I2C_IT_TXI) != RESET))  //TXIS中断
	{
      /* Write data to TXDR */
		if(hi2c->XferCount<hi2c->XferSize)
		{
      hi2c->Instance->TXDR = (*hi2c->pBuffPtr++);
      hi2c->XferCount++;
		}
		else hi2c->Instance->TXDR=0x00;
	}
	if (((itflags & I2C_FLAG_STOPF) != RESET) && ((itsources & I2C_IT_STOPI) != RESET))    //停止信号中断
	{
	  __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
		__HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
		__HAL_I2C_DISABLE_IT(&hi2c1, I2C_IT_ERRI|I2C_IT_STOPI|I2C_IT_RXI|I2C_IT_TCI|I2C_IT_NACKI|I2C_IT_ADDRI|I2C_IT_TXI); //关闭所有I2C中断
		  /* Store Last receive data if any */
		hi2c->Instance->CR2 |= I2C_CR2_NACK;   //关闭应答信号
		
		if(userI2cCmdState==I2C_CMD_RECEIVE)           //命令接收ok
		{
			userI2cCmdState=I2C_CMD_REC_END;
			user_I2cRecDeal(userI2cRecBuffer,hi2c->XferCount);			
		}
		else if((userI2cCmdState==I2C_CMD_TRANSMIT)&&(hi2c->XferCount==0)) //数据发送ok                        
		{
			userI2cCmdState=I2C_CMD_START;
			user_I2cCmdStart();
		}
		else 
		{
			userI2cCmdState=I2C_CMD_ERROR;
			user_I2cCmdError();
		}
	}

}
//I2C异常事件中断服务函数
void user_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c)
{
  uint32_t itflags   = READ_REG(hi2c->Instance->ISR);
  uint32_t itsources = READ_REG(hi2c->Instance->CR1);

  /* I2C Bus error interrupt occurred ------------------------------------*/
  if (((itflags & I2C_FLAG_BERR) != RESET) && ((itsources & I2C_IT_ERRI) != RESET))
  {
    hi2c->ErrorCode |= HAL_I2C_ERROR_BERR;
    /* Clear BERR flag */
    __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR);
  }

  /* I2C Over-Run/Under-Run interrupt occurred ----------------------------------------*/
  if (((itflags & I2C_FLAG_OVR) != RESET) && ((itsources & I2C_IT_ERRI) != RESET))
  {
    hi2c->ErrorCode |= HAL_I2C_ERROR_OVR;
    /* Clear OVR flag */
    __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR);
  }

  /* I2C Arbitration Loss error interrupt occurred -------------------------------------*/
  if (((itflags & I2C_FLAG_ARLO) != RESET) && ((itsources & I2C_IT_ERRI) != RESET))
  {
    hi2c->ErrorCode |= HAL_I2C_ERROR_ARLO;
    /* Clear ARLO flag */
    __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO);
  }
  user_I2cCmdError();	
}
//设置I2c发送
void user_I2cSetTransmit(I2C_HandleTypeDef *hi2c,uint8_t Size)
{
		hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
		hi2c->pBuffPtr=userI2cTransBuffer;
		hi2c->XferCount   = 0;
    hi2c->XferSize    = Size;
	  __HAL_I2C_ENABLE_IT(&hi2c1, I2C_IT_ADDRI|I2C_IT_ERRI);   //打开i2c地址匹配中断
}
//设置I2c接收
void user_I2cSetReceive(I2C_HandleTypeDef *hi2c)
{
		hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
		hi2c->pBuffPtr=userI2cRecBuffer;
		hi2c->XferCount   = 0;
		__HAL_I2C_ENABLE_IT(&hi2c1, I2C_IT_ADDRI|I2C_IT_ERRI);   //打开i2c地址匹配中断
}



//操作超时检测,放在定时器里面进行扫描,每10ms扫描一次
void user_I2cOverTimeCheck()
{
	
	if((userI2cCmdState!=I2C_CMD_START)&&(userI2cCmdState!=I2C_CMD_WAIT_REC))
	{
		userCmdOverTimeCheck++;
		if(userCmdOverTimeCheck>=3) //30ms还没有完成则认定为超时
		{
			userCmdOverTimeCheck=0;
			userI2cCmdState=I2C_CMD_ERROR;
			user_I2cCmdError();
		}
	}
}
//从optionByte userdata0里面读取出来地址数据
void user_I2cReadOptionAdd()
{
	userI2cOpDataAdd=HAL_FLASHEx_OBGetUserData(OB_DATA_ADDRESS_DATA0);
	if(userI2cOpDataAdd>I2C_MAX_ADDRESS)  //如果从option读出来的地址超过了最大地址，就设置为默认固定地址
	{
		userI2cOpDataAdd=I2C_FIXED_ADDRESS;
	}
}
//和MX_I2C1_Init相比只是修改了设置OwnAddress1
void user_I2cInit()
{
	user_I2cReadOptionAdd();

	HAL_I2C_DeInit(&hi2c1);
	hi2c1.Instance = I2C1;
	hi2c1.Init.Timing = 0x0000020B;
	hi2c1.Init.OwnAddress1 =(userI2cOpDataAdd<<1);
	hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
	hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
	hi2c1.Init.OwnAddress2 = 0;
	hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
	hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
	hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
	if (HAL_I2C_Init(&hi2c1) != HAL_OK)
	{
	_Error_Handler(__FILE__, __LINE__);
	}

	/**Configure Analogue filter 
	*/
	if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
	{
	_Error_Handler(__FILE__, __LINE__);
	}

	/**Configure Digital filter 
	*/
	if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
	{
	_Error_Handler(__FILE__, __LINE__);
	}	
	
	user_I2cCmdStart();
}

static void user_I2cRecDeal(uint8_t *buf,uint8_t size)
{
	uint8_t i;
	for(i=0;i<ALL_REG_NUMBER;i++)
	{
		if(buf[0]==userI2cRegList[i].regAdd)    //匹配上了列表中的命令
		{
			userI2cNowRegNum=i;
			if(userI2cRegList[userI2cNowRegNum].tr==CMD_RT_TRANSMIT)   //判断是否是从机发送命令
			{						           
				user_I2cGetTransmitData(userI2cRegList[userI2cNowRegNum].regAdd,userI2cTransBuffer);
				userI2cCmdState=I2C_CMD_WAIT_TRANSMIT;
				user_I2cSetTransmit(&hi2c1,userI2cRegList[userI2cNowRegNum].size);					
			}
			else if(userI2cRegList[userI2cNowRegNum].tr==CMD_RT_RECEIVE)
			{
				userI2cCmdState=I2C_CMD_EXECUTE;
				user_I2cExecuteCallBack(userI2cRegList[userI2cNowRegNum].regAdd,buf+1,size-1);
				userI2cCmdState=I2C_CMD_START;
				user_I2cCmdStart();				
				
			}
			break;
		}
	}
	if(userI2cNowRegNum>=ALL_REG_NUMBER)
	{
		userI2cCmdState=I2C_CMD_ERROR;    //没有匹配到命令就进入错误状态
		user_I2cCmdError();
	}		
}

void user_I2cCmdStart()
{
	userI2cRecBuffer[0]=0;
	userI2cNowRegNum=0xff;
	userCmdOverTimeCheck=0;
	hi2c1.XferCount=0;
	hi2c1.XferSize=0;
	
	user_I2cSetReceive(&hi2c1);
	userI2cCmdState=I2C_CMD_WAIT_REC;
}
static void user_I2cCmdError()
{
	__HAL_I2C_DISABLE_IT(&hi2c1, I2C_IT_ERRI|I2C_IT_STOPI|I2C_IT_RXI|I2C_IT_TCI|I2C_IT_NACKI|I2C_IT_ADDRI|I2C_IT_TXI); //关闭所有I2C中断
	user_I2cFlushTxdr(&hi2c1);
	user_I2cSoftReset(&hi2c1);			
	userI2cCmdState=I2C_CMD_START;
	user_I2cCmdStart();	
}

//获取要发送的数据，返回-1为错误，其他值为返回的数据长度
//cmd为命令，buf用来存放获取到的数据
__weak uint8_t user_I2cGetTransmitData(uint8_t reg,uint8_t *buf)
{
	return 1;
}
//命令执行函数
__weak void user_I2cExecuteCallBack(uint8_t reg,uint8_t *buf,uint8_t size)
{

}
